#include "cardgraphicsitem.h"

#include "imageprovider.h"

#include "mainwindow.h"
#include "cardlistmodel.h"

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QPainter>
#include <QPropertyAnimation>
#include <QGraphicsSceneMouseEvent>
#include <limits>

#include <QAction>
#include <QMenu>

#include <QInputDialog>

#include "carddisplaydock.h"

Q_DECLARE_METATYPE(CardListModel*);

static qreal topOrderZ = std::numeric_limits<qreal>::min();

CardGraphicsItem::CardGraphicsItem(const QString &multiverseId) :
    m_multiverseId(multiverseId), tapped(false)
{
    setFlag(ItemIsMovable);

    setShapeMode(BoundingRectShape);

    //setTransformationMode(Qt::SmoothTransformation);

    setScale(0.5);

    setTransformOriginPoint(223/2, 310/2) ;

    ImageProvider::instance().requestImage(m_multiverseId, this, SLOT(changePixmap(QPixmap)));
}

void CardGraphicsItem::mouseDoubleClickEvent ( QGraphicsSceneMouseEvent * event )
{
    QGraphicsPixmapItem::mouseDoubleClickEvent(event);

    tapped = !tapped;

    QPropertyAnimation *animation = new QPropertyAnimation(this, "rotation");
    animation->setDuration(200);


    if (tapped) {
        animation->setStartValue(0);
        animation->setEndValue(90);
    }
    else {

        animation->setStartValue(90);
        animation->setEndValue(0);
    }
    animation->start(QPropertyAnimation::DeleteWhenStopped);
}

void CardGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
    QGraphicsPixmapItem::mousePressEvent(event);

    if (zValue() != topOrderZ)
    {
        topOrderZ += std::numeric_limits<qreal>::epsilon();
        setZValue(topOrderZ);
    }

    CardDisplayDock::instance().displayCard(m_multiverseId);
}

void CardGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    if (event->button() == Qt::RightButton) {
        QMenu *menu = new QMenu();

        QAction *action;
        action = new QAction(tr("Send to Hand"), menu);
        connect(action, SIGNAL(triggered()), SLOT(sendToHand()));
        menu->addAction(action);

        action = new QAction(tr("Send to Graveyard"), menu);
        connect(action, SIGNAL(triggered()), SLOT(sendToGraveyard()));
        menu->addAction(action);

        action = new QAction(tr("Send to Library Top"), menu);
        connect(action, SIGNAL(triggered()), SLOT(sendToLibraryTop()));
        menu->addAction(action);

        action = new QAction(tr("Send to Library Bottom"), menu);
        connect(action, SIGNAL(triggered()), SLOT(sendToLibraryBottom()));
        menu->addAction(action);

        menu->addSeparator();

        action = new QAction(tr("Set Power/Thoughness"), menu);
        connect(action, SIGNAL(triggered()), SLOT(setPowerAndThouthness()));
        menu->addAction(action);

        menu->exec(QCursor::pos());
        delete menu;
    }
    else {
        QGraphicsPixmapItem::mouseReleaseEvent(event);
    }
}

QRectF CardGraphicsItem::boundingRect () const
{
    if (!pixmap().isNull()) {
        return QGraphicsPixmapItem::boundingRect();
    }
    else {
        return QRectF(0, 0, 223, 310);
    }
}

bool CardGraphicsItem::contains ( const QPointF & point ) const
{
    if (!pixmap().isNull()) {
        return QGraphicsPixmapItem::contains(point);
    }
    else {
        return boundingRect().contains(point);
    }
}

void CardGraphicsItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget )
{
    QRectF bounds = boundingRect();
    if (!pixmap().isNull()) {
        QGraphicsPixmapItem::paint(painter, option, widget);
    }
    else {
        painter->drawRect(bounds);
    }

    if (!powerAndThouthness.isEmpty()) {

        QFont f = painter->font();
        f.setPointSize(20);
        f.setBold(true);
        painter->setFont(f);

        QRect textRect = painter->fontMetrics().boundingRect(powerAndThouthness);

        textRect.moveTo(bounds.width()-textRect.width() - 15, bounds.height()-textRect.height() - 15);

        textRect.adjust(-5, -5, 5, 5);

        painter->setPen(QPen(Qt::darkGray, 4));
        painter->setBrush(Qt::lightGray);

        painter->drawRoundedRect(textRect, 8, 8);

        painter->setPen(Qt::black);

        painter->drawText(textRect, powerAndThouthness, Qt::AlignCenter | Qt::AlignHCenter);
    }
}

void CardGraphicsItem::shrink(CardListModel *destiny, bool top)
{
    QPropertyAnimation *animation = new QPropertyAnimation(this, "scale");
    animation->setDuration(200);

    animation->setStartValue(0.5);
    animation->setEndValue(0);

    connect(animation, SIGNAL(finished()), SLOT(animationFinished()));
    animation->setProperty("destiny", QVariant::fromValue(destiny));
    animation->setProperty("top", top);

    animation->start(QPropertyAnimation::DeleteWhenStopped);
}

void CardGraphicsItem::animationFinished()
{
    QPropertyAnimation *ann = static_cast<QPropertyAnimation*>(sender());

    scene()->removeItem(this);
    setScale(0.5);

    CardListModel *destiny = ann->property("destiny").value<CardListModel*>();
    bool top = ann->property("top").toBool();
    destiny->addCard(this, top);
}

void CardGraphicsItem::setPowerAndThouthness()
{
    QString result = powerAndThouthness;
    QWidget *parent = scene()->views().front();
    result = QInputDialog::getText(parent, "MagiQt", tr("Set power/thouthness"), QLineEdit::Normal, result);

    if (!result.isNull()) {
        powerAndThouthness = result;
        update();
    }
}

void CardGraphicsItem::sendToHand()
{
    shrink(MainWindow::instance->hand);
}

void CardGraphicsItem::sendToLibraryTop()
{
    shrink(MainWindow::instance->library, true);
}

void CardGraphicsItem::sendToLibraryBottom()
{
    shrink(MainWindow::instance->library);
}

void CardGraphicsItem::sendToGraveyard()
{
    shrink(MainWindow::instance->graveyard);
}

void CardGraphicsItem::sendExile()
{

}

void CardGraphicsItem::sendToBattleField()
{
    MainWindow::instance->battleField->addItem(this);

    tapped = false;
    setRotation(0);

    setPos(scene()->sceneRect().center() - boundingRect().center());

    topOrderZ += std::numeric_limits<qreal>::epsilon();
    setZValue(topOrderZ);

    QPropertyAnimation *animation = new QPropertyAnimation(this, "scale");
    animation->setDuration(200);

    animation->setStartValue(0);
    animation->setEndValue(0.5);

    animation->start(QPropertyAnimation::DeleteWhenStopped);
}
